﻿using EMall.Cache;
using EMall.Domain;
using EMall.ProductService.Categories;
using MediatR;

namespace EMall.ProductService
{
    public class CacheRefreshEventHandler : Events.EventHandler,
        INotificationHandler<CacheRefreshEvent>,
        INotificationHandler<EntityCreatedDomainEvent<Category>>,
        INotificationHandler<EntityUpdatedDomainEvent<Category>>
    {
        private readonly ICacheManager CacheManager;
        private readonly ICategoryAppService _categoryAppService;
        private Dictionary<string, Func<Task>> Handles = new Dictionary<string, Func<Task>>();
        public CacheRefreshEventHandler(ICacheManager cacheManager, ICategoryAppService categoryAppService)
        {
            CacheManager = cacheManager;
            _categoryAppService = categoryAppService;
            RegisterHandles();
        }
        private void RegisterHandles()
        {
            Handles.Add(typeof(CategoryTree).Name.ToLower(), CategoryTreeRefreshAsync);
        }
        private Task CategoryTreeRefreshAsync()
        {
            return CacheManager.TryRefreshValueAsync(typeof(CategoryTree).Name.ToLower(), _categoryAppService.GetTreeAsync);
        }
        public async Task Handle(CacheRefreshEvent notification, CancellationToken cancellationToken)
        {
            foreach (var key in notification.Keys)
            {
                if (Handles.TryGetValue(key, out var handle))
                {
                    await handle.Invoke();
                }
            }
        }
        public async Task Handle(EntityCreatedDomainEvent<Category> notification, CancellationToken cancellationToken)
        {
            if (Handles.TryGetValue(typeof(CategoryTree).Name.ToLower(), out var handle))
            {
                await handle.Invoke();
            }
        }
        public async Task Handle(EntityUpdatedDomainEvent<Category> notification, CancellationToken cancellationToken)
        {
            if (Handles.TryGetValue(typeof(CategoryTree).Name.ToLower(), out var handle))
            {
                await handle.Invoke();
            }
        }
    }
}
